package com.example.channel

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.junit.Test


/**
 * 路由通道测试
 *
 * produce和actor
 * 1）构建生产者和消费者的便捷方法
 * 2）我们可以通过produce方法来启动一个生产者协程，
 * 并返回ReceiveChanel，其他协程就可以使用这个Channel来接收数据了。
 * 反过来，我们可以使用actor启动一个消费者协程。
 *
 * @author zhouronghua
 * @time 2022/1/4 7:32 下午
 */
class CoroutineChannelTest {
    /**
     * 测试路由通道容量
     *
     * @author zhouronghua
     * @time 2022/1/4 7:33 下午
     */
    @Test
    fun testChanelCapacity() = runBlocking {
        // 生产者
        val channel = Channel<Int>(Channel.UNLIMITED)
        val producer = GlobalScope.launch {
            for (i in 1 .. 1000) {
                println("send $i")
                channel.send(i)
            }
        }
        // 消费者
        val consumer = GlobalScope.launch {
            while (true) {
                val element = channel.receive()
                println("receive $element")
                delay(200)
            }
        }
        joinAll(producer, consumer)
    }

    /**
     * 测试produce方法发送
     *
     *
     * @author zhouronghua
     * @time 2022/1/4 8:03 下午
     */
    @Test
    fun test_channel_produce() = runBlocking {
        // 构建一个生产者协程
        val receiveChannel: ReceiveChannel<Int> = GlobalScope.produce {
            for (i in 1 .. 1000) {
                println("send $i ${Thread.currentThread().name}")
                send(i)
            }
        }
        val consumer = GlobalScope.launch {
            for (element in receiveChannel) {
                println("receive $element")
            }
        }
        consumer.join()
    }

    /**
     * 测试actor方法发送
     *
     * @author zhouronghua
     * @time 2022/1/4 8:03 下午
     */
    @Test
    fun test_channel_actor() = runBlocking {
        // 消费者协程
        val sendChannel: SendChannel<Int> = GlobalScope.actor<Int> {
            while (true) {
                var element = receive()
                println("receive $element")
            }
        }
        // 创建生产者协程
        val producer = GlobalScope.launch {
            for (i in 1 .. 1000) {
                println("send $i")
                sendChannel.send(i)
            }
        }
        producer.join()
    }

    /**
     * 测试迭代器方法发送
     *
     * @author zhouronghua
     * @time 2022/1/4 8:03 下午
     */
    @Test
    fun test_channel_iterator() = runBlocking {
        println("=====测试Channel迭代器======")
        // 消费者协程
        val sendChannel: SendChannel<Int> = GlobalScope.actor<Int> {
            // 使用迭代器获取通道元素
            var it = iterator()
            while (it.hasNext()) {
                var element = it.next()
                println("receive $element")
            }
        }
        // 创建生产者协程
        val producer = GlobalScope.launch {
            for (i in 1 .. 1000) {
                println("send $i")
                sendChannel.send(i)
            }
        }
        producer.join()
    }
}